---
title: Макеты
description: Введение в макеты Astro.
i18nReady: true
---

import ReadMore from '~/components/ReadMore.astro'

**Макеты** — это [компоненты Astro](/ru/basics/astro-components/), которые определяют структуру пользовательского интерфейса (UI), например, шаблон страницы.

Мы условно используем термин «макет» для компонентов Astro, которые создают общие элементы UI, такие как заголовки, панели навигации и нижние колонтитулы, используемые на разных страницах. Типичный компонент макета Astro используется для предоставления [страницам Astro, Markdown или MDX](/ru/basics/astro-pages/) следующего:
- **оболочки страницы** (теги `<html>`, `<head>` и `<body>`)
- [**`<slot />`**](/ru/basics/astro-components/#слоты), чтобы указать, куда должно быть вставлено содержимое отдельной страницы.

Но в компоненте макета нет ничего особенного! Они могут [принимать свойства](/ru/basics/astro-components/#пропсы-компонента) и [импортировать и использовать другие компоненты](/ru/basics/astro-components/#структура-компонента), как и любой другой компонент Astro. Они могут включать в себя [компоненты UI-фреймворков](/ru/guides/framework-components/) и [скрипты на стороне клиента](/ru/guides/client-side-scripts/). Они даже не обязательно должны предоставлять полную оболочку страницы, вместо этого их можно использовать как частичные шаблоны пользовательского интерфейса.

Однако, если компонент макета содержит оболочку страницы, его элемент `<html>` должен быть родительским для всех остальных элементов в компоненте.

Компоненты макетов обычно размещаются в директории `src/layouts` вашего проекта для удобства организации, но это не является обязательным требованием; вы можете разместить их в любом месте вашего проекта. Вы даже можете поместить компоненты макета рядом со своими страницами, [добавив префикс `_` к именам макетов](/ru/guides/routing/#excluding-pages).

## Пример макета

```astro "<slot />" 
---
// src/layouts/MySiteLayout.astro
import BaseHead from '../components/BaseHead.astro';
import Footer from '../components/Footer.astro';
const { title } = Astro.props;
---
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <BaseHead title={title}/>
  </head>
  <body>
    <nav>
      <a href="#">Главная</a>
      <a href="#">Посты</a>
      <a href="#">Контакты</a>
    </nav>
    <h1>{title}</h1>
    <article>
      <slot /> <!--  Ваше содержимое вставляется сюда -->
    </article>
    <Footer />
  </body>
  <style>
    h1 {
      font-size: 2rem;
    }
  </style>
</html>
```

```astro title="src/pages/index.astro"
---
import MySiteLayout from '../layouts/MySiteLayout.astro';
---
<MySiteLayout title="Главная страница">
  <p>Мой контент, обёрнутый в макет!</p>
</MySiteLayout>
```

<ReadMore>Узнать больше о [слотах](/ru/basics/astro-components/#слоты).</ReadMore>

## Использование TypeScript с макетами

Любой макет Astro можно модифицировать для добавления типобезопасности и автодополнения, указав типы для ваших пропсов:

```astro ins={2-7} title="src/components/MyLayout.astro"
---
interface Props { 
  title: string;
  description: string;
  publishDate: string;
  viewCount: number;
}
const { title, description, publishDate, viewCount } = Astro.props;
---
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="description" content={description}>
    <title>{title}</title>
  </head>
  <body>
    <header>
      <p>Опубликовано {publishDate}</p>
      <p>Ознакомились {viewCount} человек</p>
    </header>
    <main>
      <slot />
    </main>
  </body>
</html>
```

## Markdown макеты

Макеты страниц особенно полезны для отдельных страниц Markdown, которые в противном случае не имели бы никакого форматирования.

Astro предоставляет специальное свойство `layout` в метаданных, предназначенное для [отдельных файлов `.md`, расположенных в `src/pages/` с использованием маршрутизации на основе файлов](/ru/guides/markdown-content/#individual-markdown-pages), чтобы указать, какой компонент `.astro` использовать в качестве макета страницы. Этот компонент позволяет вам предоставлять содержимое `<head>`, такое как метатеги (например, `<meta charset="utf-8">`) и стили для страницы Markdown. По умолчанию этот указанный компонент может автоматически получать данные из файла Markdown.

Это свойство не распознаётся как специальное при использовании [коллекций контента](/ru/guides/content-collections/) для запроса и отображения вашего контента.

```markdown title="src/pages/page.md" {2} 
---
layout: ../layouts/BaseLayout.astro
title: "Привет, мир!"
author: "Мэтью Филлипс"
date: "9 августа 2022"
---
Все свойства метаданных доступны в качестве входных параметров компонента для макета Astro.

Свойство `layout` — единственное специальное свойство, предоставляемое Astro.

Вы можете использовать его в Markdown-файлах, расположенных внутри `src/pages/`.

```

Типичный макет для страницы Markdown включает в себя:

1. Свойство `frontmatter` для доступа к метаданным и другим данным страницы Markdown. 
2. [`<slot />`](/ru/basics/astro-components/#слоты) по умолчанию, для указания места вставки содержимого страницы в формате Markdown.

```astro title="src/layouts/BlogPostLayout.astro" /(?<!//.*){?frontmatter(?:\\.\w+)?}?/ "<slot />"
---
// 1. Свойство `frontmatter` предоставляет доступ к метаданным и другим данным
const { frontmatter } = Astro.props;
---
<html>
  <head>
    <!-- Добавьте сюда другие элементы <head>, такие как стили и мета-теги. -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta charset="utf-8">
    <title>{frontmatter.title}</title>
  </head>
  <body>
    <!-- Добавьте сюда другие компоненты UI, такие как верхний и нижний колонтитулы страницы. -->
    <h1>{frontmatter.title} от {frontmatter.author}</h1>
    <!-- 2. Готовый HTML будет передан в слот по умолчанию. -->
    <slot />
    <p>Дата: {frontmatter.date}</p>
  </body>
</html>
```

Вы можете установить [тип входных параметров компонента](/ru/basics/astro-components/#пропсы-компонента) макета с помощью хелпера `MarkdownLayoutProps`:

```astro title="src/layouts/BaseLayout.astro" ins={2,4-9}
---
import type { MarkdownLayoutProps } from 'astro';

type Props = MarkdownLayoutProps<{
  // Определяем свойства объекта `frontmatter`
  title: string;
  author: string;
  date: string;
}>;

// Теперь свойства макета Markdown, такие как `frontmatter`, `url`,
// и другие, доступны с типобезопасностью
const { frontmatter, url } = Astro.props;
---
<html>
  <head>
    <meta charset="utf-8">
    <link rel="canonical" href={new URL(url, Astro.site).pathname}>
    <title>{frontmatter.title}</title>
  </head>
  <body>
    <h1>{frontmatter.title} от {frontmatter.author}</h1>
    <slot />
    <p>Дата: {frontmatter.date}</p>
  </body>
</html>
```

### Свойства макета Markdown

Макет Markdown будет иметь доступ к следующей информации через `Astro.props`:

- **`file`** - Абсолютный путь этого файла (например, `/home/user/projects/.../file.md`).
- **`url`** - Если это страница, то URL страницы (например, `/en/guides/markdown-content`).
- **`frontmatter`** - Вся мета-информация из документа Markdown или MDX.
  - **`frontmatter.file`** - То же, что и свойство верхнего уровня `file`.
  - **`frontmatter.url`** - То же, что и свойство верхнего уровня `url`.
- **`headings`** - Список заголовков (`h1 -> h6`) в документе Markdown или MDX с соответствующими метаданными. Этот список следует типу: `{ depth: number; slug: string; text: string }[]`.
- **`rawContent()`** - Функция, возвращающая необработанный документ Markdown в виде строки.
- **`compiledContent()`** - Функция, возвращающая документ Markdown, скомпилированный в HTML-строку.

:::note
Макет Markdown будет иметь доступ ко всем [доступным свойствам](/ru/guides/markdown-content/#available-properties) своего файла из `Astro.props` **с некоторыми ключевыми отличиями:**.

*   Информация о заголовках (т. е. элементы `h1 -> h6`) доступна через массив `headings`, а не через функцию `getHeadings()`.

*   `file` и `url` также *доступны как вложенные свойства `frontmatter` (т. е. `frontmatter.url` и `frontmatter.file`).

:::

### Импорт макетов вручную (MDX)

Вы также можете использовать специальное свойство макета Markdown в метаданных файлов MDX, чтобы передать пропсы `frontmatter` и `headings` напрямую в указанный компонент макета таким же образом.

Чтобы передать информацию в ваш макет MDX, которая не существует (или не может существовать) в метаданных, вы можете вместо этого импортировать и использовать компонент `<Layout />`. Это работает как любой другой компонент Astro и не будет автоматически получать никакие пропсы. Передайте ему необходимые пропсы напрямую:

```mdx title="src/pages/posts/first-post.mdx" ins={6} del={2} /</?BaseLayout>/ /</?BaseLayout title={frontmatter.title} fancyJsHelper={fancyJsHelper}>/
---
layout: ../../layouts/BaseLayout.astro
title: 'Мой первый пост MDX'
publishDate: '21 сентября 2022'
---
import BaseLayout from '../../layouts/BaseLayout.astro';

export function fancyJsHelper() {
  return "Пытаемся делать что-нибудь с помощью YAML!";
}

<BaseLayout title={frontmatter.title} fancyJsHelper={fancyJsHelper}>.
  Добро пожаловать в мой новый блог на Astro, с использованием MDX!
</BaseLayout>
```

Затем ваши значения будут доступны вам через `Astro.props` в вашем макете, и ваш MDX-контент будет внедрен на страницу, где прописан ваш компонент `<slot />`:

```astro title="src/layouts/BaseLayout.astro" /{?title}?/ "fancyJsHelper" "{fancyJsHelper()}"
---
const { title, fancyJsHelper } = Astro.props;
---
<html>
  <head>
    <!-- -->
    <meta charset="utf-8">
  </head>
  <body>
    <!-- -->
    <h1>{title}</h1>
    <slot /> <!-- здесь вставляется ваш контент -->
    <p>{fancyJsHelper()}</p>
    <!-- -->
  </body>
</html>
```

При использовании любого макета (через свойство `layout` в метаданных или путём импорта макета) вы должны включить тег `<meta charset="utf-8">` в ваш макет, так как Astro больше не добавляет его автоматически на вашу страницу MDX.

<ReadMore>Подробнее о поддержке Markdown и MDX в Astro вы можете узнать из нашего [руководства по Markdown](/ru/guides/markdown-content/).</ReadMore>

## Вложенные макеты

Компоненты макета не обязательно должны содержать целую страницу HTML. Вы можете разбить свои макеты на более мелкие компоненты и комбинировать их, чтобы создавать ещё более гибкие шаблоны страниц. Этот шаблон полезен, когда вы хотите совместно использовать некоторый код в нескольких макетах.

Например, макет компонента `BlogPostLayout.astro` может стилизовать заголовок, дату и автора статьи. Затем, глобальный макет `BaseLayout.astro` может обрабатывать остальную часть вашего шаблона страницы, такую как навигация, нижние колонтитулы, мета-теги SEO, глобальные стили и шрифты. Вы также можете передавать входные параметры, полученные из вашей статьи, в другой макет, так же как и любой другой вложенный компонент.

```astro {3} /</?BaseLayout>/ /</?BaseLayout url={frontmatter.url}>/
---
// src/layouts/BlogPostLayout.astro
import BaseLayout from './BaseLayout.astro';
const { frontmatter } = Astro.props;
---
<BaseLayout url={frontmatter.url}>
  <h1>{frontmatter.title}</h1>
  <h2>Автор поста: {frontmatter.author}</h2>
  <slot />
</BaseLayout>
```	
